'''
Created on Apr 30, 2012

@author: Ruyman Reyes
'''
from yacf.MiddleEnd.Functions.Mutators.Outliner import block_is_SESE
from yacf.Backends.Common.Visitors.GenericVisitors import FuncDefOfNameFilter,\
    FuncCallFilter
from yacf.Tools.Tree import getFileNode, NodeNotFound

class Kernelize(object):
    def init(self,):
        pass

    def is_kernelizable(self, function, loop_parameters,):
        assert block_is_SESE(function.body)
        # TODO
        #  1 - Check no pointers inside stmts
        return True
    
    def inline_called_functions(self, non_visited_funcalls, objetive, 
                    native_list, allow_native):
        """ Inline called functions 
        """
        undeclared_list = []
        visited = []
        called_list = []
        while len(non_visited_funcalls) > 0:
            try:
                elem = non_visited_funcalls.pop()
                if not allow_native or (allow_native and not elem.name in native_list):
                    print " Extracting function named: " + str(elem.name)
                    funcDef = FuncDefOfNameFilter  (name = elem.name).apply(getFileNode(objetive))
                    called_list.append(funcDef) 
                    visited.append(elem.name)
                    # Check for nested calls
                    for elem in FuncCallFilter().iterate(funcDef.body):
                        if not elem in visited:
                            non_visited_funcalls.append(elem)
                elif allow_native and elem.name in native_list:
                    print " Native call to :" + str(elem.name)
                else:
                    print " Function " + elem.name + " is neither native or declared "
                    raise NotImplemented
            except NodeNotFound:
                # Declaration could not be found
                undeclared_list.append(elem)
                continue
        if len(undeclared_list) > 0:
            print " Following functions were called but not declared: "
            print [str(elem.name) for elem in undeclared_list]
	    print " Will assume they are native "
	# Reverse list to match declaration order
        called_list.reverse()
        return called_list
        
